﻿using RoadQualityEvalAPI.Models;
using RoadQualityEvaluatorData.Domain.Entities;
using RoadQualityEvaluatorData.DomainServices.Generic;
using RoadQualityEvaluatorData.DomainServices.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace RoadQualityEvalAPI.Controllers
{
    public class UserController : ApiController
    {
        private UserRepository _userRepo;
        private RoleRepository _roleRepo;

        
        public List<UserModel> GetAllUsers()
        {
            this._userRepo = new UserRepository();

            List<UserModel> users = new List<UserModel>();

            foreach (var x in _userRepo.GetAll())
            {
                users.Add(new UserModel()
                    {
                        CreatedAt = x.CreatedAt,
                        Email = x.Email, 
                        UserInfo = x.Info,
                        UserName = x.Username
                    });
            }

            return users;
        }

        public UserModel GetUserById(int id)
        {
            _userRepo = new UserRepository();

            var u = _userRepo.GetById(id);

            return new UserModel()
            {
                CreatedAt = u.CreatedAt,
                Email = u.Email,
                UserInfo = u.Info,
                UserName = u.Username
            };
        }

        public UserModel GetUserByUsername(string username)
        {
            _userRepo = new UserRepository();

            var u = _userRepo.GetUserByUsername(username);

            return new UserModel()
            {
                CreatedAt = u.CreatedAt,
                Email = u.Email,
                UserInfo = u.Info,
                UserName = u.Username
            };
        }


        public RoleModel GetRoleByName (string roleName)
        {
            _roleRepo = new RoleRepository();

            var role = _roleRepo.GetRoleByName(roleName);

            return new RoleModel() { RoleName = role.RoleName, RoleInfo = role.RoleDescription };
        }

        public List<RoleModel> GetAllRoles()
        {
            _roleRepo = new RoleRepository();

            List<RoleModel> roles = new List<RoleModel>();

            foreach (var r in _roleRepo.GetAll())
            {
                RoleModel role = new RoleModel()
                {
                    RoleInfo = r.RoleDescription,
                    RoleName = r.RoleName
                };

                roles.Add(role);
            }

            return roles;
        }

        [HttpPost]
        public void CreateNewRole(RoleModel role)
        {
            _roleRepo = new RoleRepository();

            try
            {
                _roleRepo.Add(new Role()
                {
                    RoleDescription = role.RoleInfo,
                    RoleName = role.RoleName
                });
            }
            catch (Exception ex)
            { }
           
        }

        

        [HttpPost]
        public void CreateNewUser(UserModel user)
        {
            UnitOfWork uo = new UnitOfWork();
            _userRepo = new UserRepository(uo);
            _roleRepo = new RoleRepository(uo);

            try
            {
                if (_userRepo.GetUserByUsername(user.UserName) == null)
                {
                    var userToAdd = new User()
                    {
                        CreatedAt = DateTime.Now,
                        Email = user.Email,
                        Info = user.UserInfo,
                        HashedPassword = user.HashedPass,
                        Username = user.UserName
                    };
                    _userRepo.Add(userToAdd);

                    // TODO: add client role to added users
                    var role = _roleRepo.GetRoleByName("Client");
                    userToAdd.UserRoles = new List<Role>();
                    userToAdd.UserRoles.Add(role);
                    _userRepo.Update(userToAdd);
                }
                else
                {
                    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Conflict));
                }
            }
            catch (Exception ex)
            {
                //TODO: finalize here...
            }
        }


        [HttpPost]
        public void UpdateUser(UserModel user)
        {
            _userRepo = new UserRepository();

            try
            {
                User u = _userRepo.GetUserByUsername(user.UserName);
                u.Info = user.UserInfo;
                u.Username = user.UserName;
                u.CreatedAt = user.CreatedAt;
                u.Email = user.Email;

                _userRepo.Update(u);
            }
            catch (Exception ex)
            {

            }
        }


        [HttpPost]
        public void AddRoleToUser(string roleName, UserModel userModel)
        {
            _userRepo = new UserRepository();
            var user = _userRepo.GetUserByUsername(userModel.UserName);
            _userRepo.AddExistingRoleToUser(roleName, user);
        }


        [HttpPost]
        public HttpResponseMessage CheckUserCredentials(LoginModel login)
        {
            UnitOfWork uo = new UnitOfWork();
            _userRepo = new UserRepository(uo);
            _roleRepo = new RoleRepository(uo);

            try
            {
                var user = _userRepo.GetUserByUsername(login.UserName);
                if (user != null)
                {
                    if (user.HashedPassword.Equals(login.Password) && user.UserRoles.Contains(_roleRepo.GetRoleByName("Client")))
                        return new HttpResponseMessage(HttpStatusCode.OK);
                    else
                        return new HttpResponseMessage(HttpStatusCode.Forbidden);
                }
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Conflict));
            }

            return new HttpResponseMessage(HttpStatusCode.Forbidden);
        }

    }
}
